<?php
/* 
 * Copyright (c) 2011 Antoine d'Otreppe de Bouvette
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * Manages template inheritance and placeholders. 
 */
class BlockManager {
    /**
     * @var TemplateProvider
     */
    private $templateProvider;
    
    /**
     * @var Template
     */
    private $next;
    
    /**
     * @var array
     */
    private $blocks;
    
    /**
     * @var string
     */
    private $body;
    
    /**
     * @var string the name of the block started via $this->start();
     */
    private $started;
    
    public function __construct(SimpleTemplateProvider $provider) {
        $this->templateProvider = $provider;
        $this->blocks = array();
    }
    
    /**
     * @param string $templateName 
     */
    public function extend($templateName) {
        $this->next = $this->templateProvider->getTemplate($templateName);
    }
    
    /**
     *
     * @return Template The parent template, or null if none
     */
    public function getAndClearParent() {
        $next = $this->next;
        $this->next = null;
        return $next;
    }
    
    /**
     * @return boolean true if the last rendered template has a parent
     */
    public function hasNext() {
        return $this->next !== null;
    }
    
    /**
     * Prints the body of the previous template to stdout 
     */
    public function putBody() {
        echo $this->body;
    }
    
    public function getBody() {
        return $this->body;
    }
    
    public function setBody($body) {
        $this->body = $body;
    }
    
    public function echoEscaped($block) {
        echo escape($this->get($block));
    }
    
    public function put($block) {
        echo $this->get($block);
    }
    
    public function set($block, $value) {
        $this->blocks[$block] = $value;
    }
    
    public function get($block, $default=null) {
        return array_get($this->blocks, $block, $default);
    }
    
    public function add($block, $value) {
        $this->blocks[$block][] = $value;
    }
    
    public function start($block) {
        $this->started = $block;
        ob_start();
    }
    
    public function stop() {
        $this->blocks[$this->started] = ob_get_clean();
        $this->started = null;
    }
    
    public function forceStop() {
        if ($this->started) {
            $this->stop();
        }
    }
}
